home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / program / asm32.zip / STARTDP.ASM < prev    next >
Assembly Source File  |  1995-10-13  |  12KB  |  424 lines

  1. ; STARTDP.ASM - 32-bit DPMI startup code for ASM32/DPMI
  2. ;  Original code by Tran (a.k.a. Thomas Pytel)
  3. ;  Modified August 1995 for ASM32/DPMI by Douglas Herr
  4.  
  5. ; Assemble with TASM 2.0 or newer:
  6. ; TASM /M2 STARTDP;
  7.  
  8. .386p
  9. locals
  10.  
  11. ; tell linker where library code is
  12. includelib    asm32dp.lib
  13.  
  14. STACKLEN    = 4000h         ; size of stack in bytes
  15.  
  16. PMODE_TEXT      segment para public use16 'CODE'
  17. PMODE_TEXT      ends
  18. _TEXT           segment byte public use32 'CODE'
  19. _TEXT           ends
  20. _DATA           segment dword public use32 'DATA'
  21. _DATA           ends
  22. EXE_STACK       segment para stack use16 'STACK'
  23. EXE_STACK       ends
  24.  
  25. DGROUP          group   _DATA
  26. assume  cs:_TEXT, ds:DGROUP
  27.  
  28. PMODE_TEXT      segment para public use16 'CODE'
  29. assume  cs:PMODE_TEXT, ds:PMODE_TEXT
  30.  
  31. ;═════════════════════════════════════════════════════════════════════════════
  32. align 2
  33. errmsgtbl       dw      errmsg0,errmsg1,errmsg2,errmsg3
  34.                 dw      errmsg4,errmsg5,errmsg6
  35.  
  36. errmsg0         db      'Not enough low memory!',13,10,36
  37. errmsg1         db      '80386 or better not detected!',13,10,36
  38. errmsg2         db      'No DPMI found!',13,10,36
  39. errmsg3         db      'DPMI host is not 32bit!',13,10,36
  40. errmsg4         db      'Could not enable A20 gate!',13,10,36
  41. errmsg5         db      'Could not enter DPMI 32bit protected mode!',13,10,36
  42. errmsg6         db      'Could not allocate needed DPMI selectors!',13,10,36
  43.  
  44. ;═════════════════════════════════════════════════════════════════════════════
  45. start:
  46.     push    cs            ; DS = CS
  47.         pop    ds
  48.  
  49. ; release unused DOS memory
  50.     mov    bx,ZSEG
  51.     mov    ax,es
  52.     sub    bx,ax
  53.     mov    ah,4Ah
  54.     int    21h
  55.  
  56.     push    cs
  57.     call    near ptr _pm_info    ; get information
  58.     jnc    short @@startf0        ; if no error, go on
  59.  
  60. @@startf1:
  61.     mov    si,ax            ; print error message for code AX
  62.         add    si,ax
  63.         mov    dx,errmsgtbl[si]
  64.         mov    ah,9
  65.         int    21h
  66.         mov    ax,4cffh
  67.         int    21h
  68.  
  69. @@startf0:
  70.     xor    ax,ax            ; check low memory and allocate low
  71.     mov    cx,ss            ;  buffer needed for protected mode
  72.     add    cx,STACKLEN
  73.         movzx    edx,word ptr es:[2]
  74.         sub    dx,cx
  75.         cmp    dx,bx
  76.         jb    @@startf1
  77.         mov    es,cx
  78.  
  79.     mov    ax,DGROUP
  80.     mov    ds,ax
  81.     push    cs
  82.     call    near ptr _pm_init    ; enter protected mode
  83.     jc    @@startf1        ; if error, go to error message
  84.     push    es            ; save PSP selector
  85.  
  86.     mov    cx,1            ; allocate 1 descriptor
  87.     xor    ax,ax
  88.     int    31h
  89.  
  90.     mov    bx,ax            ; BX = descriptor allocated
  91.  
  92.         mov    dx,0ffffh        ; set size to 4G
  93.         mov    cx,dx
  94.         mov    ax,8
  95.         int    31h
  96.  
  97.     mov    edx,_TEXT        ; base address = 32bit code segment
  98.         shl    edx,4
  99.         shld    ecx,edx,16
  100.         mov    ax,7
  101.         int    31h
  102.  
  103.     mov    ax,cs            ; set descriptor type to 32bit code
  104.     lar    cx,ax            ;  at the current CPL
  105.         mov    cl,ch
  106.         mov    ch,0c0h
  107.         mov    ax,9
  108.         int    31h
  109.  
  110.     mov    bp,bx            ; preserve 32bit code selector
  111.     mov    bx,ds            ; BX = current data selector
  112.  
  113.         mov    dx,0ffffh        ; set size to 4G
  114.         mov    cx,dx
  115.         mov    ax,8
  116.         int    31h
  117.  
  118.     mov    edx,DGROUP        ; base address = 32bit data segment
  119.         shl    edx,4
  120.         shld    ecx,edx,16
  121.         mov    ax,7
  122.         int    31h
  123.  
  124.         cli                             ; we don't want to be interrupted
  125.                     ;  while changing SS:ESP
  126.  
  127. ; set all segment registers to data selector
  128.     mov    es,bx        
  129.         mov    fs,bx
  130.         mov    gs,bx
  131.         mov    ss,bx
  132.  
  133. assume  ds:DGROUP
  134.  
  135.     mov    eax,EXE_STACK        ; adjust ESP for new base of stack
  136.         mov    ebx,DGROUP
  137.         sub    eax,ebx
  138.         shl    eax,4
  139.         add    esp,eax
  140.  
  141.         sti
  142.  
  143.     pop    psp_sel
  144.  
  145.     push    ebp            ; push target CS:EIP in 32bit code
  146.         db    66h,68h
  147.         dd    offset start32
  148.  
  149.     db    66h            ; 32bit RETF to 32bit code
  150.         retf
  151.  
  152. PMODE_TEXT      ends
  153.  
  154. public    $zerosel, $pspsel, $aliassel
  155. extrn   main32:near
  156.  
  157. _TEXT           segment byte public use32 'CODE'
  158. assume  cs:_TEXT
  159.  
  160. ;═════════════════════════════════════════════════════════════════════════════
  161. start32:
  162.  
  163. ; initialize selector for linear address 00000000h
  164.     mov    cx,1            ; allocate 1 descriptor
  165.     xor    ax,ax
  166.     int    31h
  167.  
  168.     mov    bx,ax            ; BX = descriptor allocated
  169.     mov    zero_sel,ax
  170.  
  171.     mov    dx,0ffffh        ; set size to 4G
  172.     mov    cx,dx
  173.     mov    ax,8
  174.     int    31h
  175.  
  176.     xor    edx,edx            ; base address = 00000000h
  177.     mov    ecx,edx
  178.     mov    ax,7
  179.     int    31h
  180.  
  181.     call    main32            ; call main code
  182.  
  183.     mov    ah,4Ch            ; exit to DOS
  184.     int    21h
  185.  
  186. $zerosel:
  187.     mov    ax,zero_sel
  188.     ret
  189.  
  190. $pspsel:
  191.     mov    ax,psp_sel
  192.     ret
  193.  
  194. $aliassel:
  195.     jmp    [alias_proc]
  196. get_alias:
  197.     mov    alias_proc,offset @curseg:alias2ax
  198.     push    ebx
  199.     mov    bx,cs
  200.     mov    ax,0Ah
  201.     int    31h
  202.     pop    ebx
  203.     mov    alias_sel,ax
  204. alias2ax:
  205.     mov    ax,alias_sel
  206.     ret
  207.  
  208. @curseg    ends
  209.  
  210. public    zero_sel, psp_sel
  211.  
  212. _DATA           segment dword public use32 'DATA'
  213. zero_sel    dw ?
  214. psp_sel        dw ?
  215. alias_sel    dw ?
  216. alias_proc    dd get_alias
  217.  
  218. @curseg    ends
  219.  
  220.  
  221. EXE_STACK       segment para stack use16 'STACK'
  222.                 db      STACKLEN dup(?)
  223. @curseg    ends
  224.  
  225.  
  226. ; ASM32/DPMI protected mode interface kernel.
  227. ; derived from Tran's PMODE 3.0b
  228.  
  229. .386p
  230. locals
  231. PMODE_TEXT      segment para public use16 'CODE'
  232. assume  cs:PMODE_TEXT, ds:PMODE_TEXT
  233.  
  234.  
  235. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  236. ; DATA
  237. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  238.  
  239. align 4
  240. dpmiepmode      dd      ?               ; DPMI enter pmode addx
  241.  
  242.  
  243. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  244. ; DETECT/INIT CODE
  245. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  246.  
  247. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  248. ; Get protected mode info
  249. ; Out:
  250. ;   AX - return code:
  251. ;     0000h - successful
  252. ;     0001h - no 80386+ detected
  253. ;     0002h - system already in protected mode and no VCPI or DPMI found
  254. ;     0003h - DPMI - host is not 32bit
  255. ;   CF - set on error, if no error:
  256. ;     BX - number of paragraphs needed for protected mode data (may be 0)
  257. ;     CL - processor type:
  258. ;       03h - 80386
  259. ;       04h - 80486
  260. ;       05h - 80586
  261. ;       06h-FFh - reserved for future use
  262. ;     CH - protected mode type:
  263. ;       00h - raw
  264. ;       01h - XMS
  265. ;       02h - VCPI
  266. ;       03h - DPMI
  267. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  268. _pm_info:
  269.         push dx si di ds es bx cx       ; preserve registers
  270.  
  271.     push    cs            ; DS = CS (PMODE_TEXT)
  272.     pop    ds
  273.  
  274.     mov    ax,1687h        ; check for DPMI
  275.     int    2fh
  276.     test    ax,ax            ; DPMI present?
  277.     mov    ax,2            ; no DPMI error code
  278.     jnz    short @@infofail
  279.  
  280.     mov    ax,3            ; error code in case DPMI not 32bit
  281.     test    bl,1            ; is DPMI 32bit?
  282.     jz    @@infofail        ; if no, fail
  283.  
  284.         mov ax,1                        ; error code in case no processor 386+
  285.         cmp cl,3                        ; is processor 386+?
  286.         jb @@infofail                   ; if no, fail
  287.  
  288.         mov word ptr dpmiepmode[0],di   ; store DPMI initial mode switch addx
  289.         mov word ptr dpmiepmode[2],es
  290.  
  291.         mov bx,si                       ; BX = number of paragraphs needed
  292.         mov ch,3                        ; pmode type is 3 (DPMI)
  293.  
  294.         add sp,4                        ; skip BX and CX on stack
  295.         xor ax,ax                       ; success code, also clear carry flag
  296.     jmp    short @@infodone
  297.  
  298. ;-----------------------------------------------------------------------------
  299. @@infofail:
  300.         pop cx bx                       ; restore BX and CX
  301.         stc                             ; carry set, failed
  302.         jmp short @@infodone
  303.  
  304. ;-----------------------------------------------------------------------------
  305. @@infodone:
  306.         pop es ds di si dx              ; restore other registers
  307.         retf                            ; return
  308.  
  309.  
  310. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  311. ; Initialize protected mode
  312. ; In:
  313. ;   ES - real mode segment for protected mode data (ignored if not needed)
  314. ; Out:
  315. ;   AX - return code:
  316. ;     0000h - successful
  317. ;     0001h - no 80386+ detected
  318. ;     0002h - system already in protected mode and no VCPI or DPMI found
  319. ;     0003h - DPMI - host is not 32bit
  320. ;     0004h - could not enable A20 gate
  321. ;     0005h - DPMI - could not enter 32bit protected mode
  322. ;     0006h - DPMI - could not allocate needed selectors
  323. ;   CF - set on error, if no error:
  324. ;     ESP - high word clear
  325. ;     CS - 16bit selector for real mode CS with limit of 64k
  326. ;     SS - selector for real mode SS with limit of 64k
  327. ;     DS - selector for real mode DS with limit of 64k
  328. ;     ES - selector for PSP with limit of 100h
  329. ;     FS - 0 (NULL selector)
  330. ;     GS - 0 (NULL selector)
  331. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  332. _pm_init:
  333.         push bx cx                      ; get initial info on protected mode
  334.     push    cs
  335.         call    near ptr _pm_info
  336.         pop cx bx
  337.         jnc short @@initf0              ; error?
  338.  
  339.         retf                            ; yup, abort
  340.  
  341. @@initf0:                               ; no error, init protected mode
  342.         pushad
  343.         push ds
  344.         mov bp,sp
  345.         push cs                         ; DS = PMODE_TEXT
  346.         pop ds
  347.         cld
  348.  
  349. ;═════════════════════════════════════════════════════════════════════════════
  350. ; DPMI protected mode init
  351. ;═════════════════════════════════════════════════════════════════════════════
  352.         pop ds                          ; get original caller DS from stack
  353.         mov ax,1                        ; enter DPMI protected mode
  354.         call cs:dpmiepmode
  355.         push ds                         ; put DS back onto stack
  356.         jnc short dvxr_init             ; error? if not, go on with init
  357.  
  358.         mov bx,6                        ; error entering protected mode, set
  359.         cmp ax,8011h                    ;  error code and abort
  360.         stc
  361.         je short init_done
  362.         mov bl,5                        ; error code 5, not 6
  363.  
  364. ;-----------------------------------------------------------------------------
  365. init_done:                              ; return with return code
  366.         mov [bp+30],bx
  367.         pop ds
  368.         popad
  369.         retf
  370.  
  371. ;─────────────────────────────────────────────────────────────────────────────
  372. dvxr_init:                              ; DPMI/VCPI/XMS/raw common init tail
  373.         mov bx,cs                       ; BX = CS if needed for same seg exit
  374.         cmp word ptr [bp+36],@curseg    ; call came from same segment?
  375.         je short @@dvxr_initdone        ; if yes, done now
  376.  
  377.         xor ax,ax                       ; allocate selector for return code
  378.         mov cx,1
  379.         int 31h
  380.         jnc short @@dvxr_initf0
  381.  
  382.         mov ah,4ch                      ; could not allocate selector
  383.         int 21h                         ; terminate immediately
  384.  
  385. @@dvxr_initf0:
  386.         mov bx,ax                       ; new code descriptor for return
  387.  
  388.         mov ax,0007h                    ; set base address of calling segment
  389.         xor cx,cx
  390.         mov dx,[bp+36]
  391.         shld cx,dx,4
  392.         shl dx,4
  393.         int 31h
  394.  
  395.         mov ax,0008h                    ; set selector limit of 64k
  396.         xor cx,cx
  397.         mov dx,0ffffh
  398.         int 31h
  399.  
  400.         mov ax,0009h                    ; set selector type and access rights
  401.         mov dx,cs                       ; get DPL from current CPL, and access
  402.         lar cx,dx                       ;  rights and type from current CS
  403.         shr cx,8                        ; type is already 16bit code segment
  404.         int 31h
  405.  
  406. @@dvxr_initdone:
  407.         mov [bp+36],bx                  ; store selector in return address
  408.         xor bx,bx                       ; init successful, carry clear
  409.         jmp init_done
  410.  
  411.  
  412. @curseg    ends
  413.  
  414. ;
  415. ; mark the end of the program
  416. ;
  417. ZSEG    segment para use16 'ZSEG'
  418. copyright    db 0Dh,0Ah
  419.         db 'ASM32/DPMI Copyright (C) 1995 Douglas Herr'
  420.         db 0Dh,0Ah
  421. @curseg    ends
  422.  
  423.     end    start
  424.